﻿using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;

namespace SaveAuditEvents
{
    class Program
    {
        struct EventLogItem
        {
            public string Server;
            public string DocLocation;
            public string Event;
            public DateTime Occurred;
            public string LoginName;
            public string Name;
            public string Source;
            public string ItemId;
            public string LocationType;
        };

        static void Main(string[] args)
        {
            using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["TSIPAuditEventLogConnectionString"].ConnectionString))
            {
                conn.Open();
                #region ---- Variables ----
                //Variables with default values
                string[] siteurls =null;
                string[] eventTypesToSave= null;
                bool clearAuditHistory = false;
                #endregion

                #region ---- Set values from app.config ----
                Console.WriteLine("Reading settings from app.config");
                try
                {
                    siteurls = ConfigurationManager.AppSettings["Site"].Split(';');
                }
                catch (Exception ex) { Console.WriteLine("Site: " + ex.Message); Environment.Exit(0); }
                try
                {
                    eventTypesToSave = ConfigurationManager.AppSettings["EventTypesToSave"].Split(';');
                }
                catch (Exception ex) { Console.WriteLine("EventTypesToSave: " + ex.Message); Environment.Exit(0); }

                try
                {
                    clearAuditHistory = bool.Parse(ConfigurationManager.AppSettings["ClearAuditHistory"]);
                }
                catch (Exception ex) { Console.WriteLine("ClearAuditHistory: " + ex.Message); Environment.Exit(0); }
                Console.WriteLine("Site(s):                       " + ConfigurationManager.AppSettings["Site"]);
                Console.WriteLine("EventTypesToSave:              " + ConfigurationManager.AppSettings["EventTypesToSave"]);
                Console.WriteLine("ClearAuditHistory:               " + clearAuditHistory.ToString());
                #endregion

                foreach (string siteurl in siteurls)
                {
                    Console.WriteLine("site:" + siteurl);
                    IterateSites(siteurl, conn, clearAuditHistory, eventTypesToSave);
                }
            }
        }
        #region ---- Methods -----
        private static void IterateSites(string siteurl, SqlConnection conn, bool clearAuditHistory,string[] eventTypesToSave)
        {
            SPWebApplication webApp = null;
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    webApp = SPWebApplication.Lookup(new Uri(siteurl));
                    int sitecount = 0;
                    SPSiteCollection siteCollections = webApp.Sites;

                    foreach (SPSite site in siteCollections)
                    {
                        try
                        {
                            sitecount++;
                            ReadAuditEntriesOfSpecificType(siteurl, site, eventTypesToSave, conn, clearAuditHistory);
                            Console.WriteLine(sitecount+" of "+siteCollections.Count);
                        }

                        catch (Exception ex)
                        {
                            Console.WriteLine("Error in application: " + ex.Message + " site:" + site.ServerRelativeUrl);
                            continue;
                        }
                        finally
                        {
                            site.Dispose();
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine("RunWithElevatedPrivileges error: " + ex.Message + " " + webApp.DisplayName);
            }
            finally
            {
                
            }
            Console.WriteLine("Done");
        }
        private static void ReadAuditEntriesOfSpecificType(string siteurl, SPSite site, string[] eventTypesToSave, SqlConnection conn, bool clearAuditHistory)
        {
            using (SPWeb web = site.OpenWeb())
            {
                SPAuditQuery wssQuery = new SPAuditQuery(site);
                SPAuditEntryCollection auditCol;
                auditCol = site.Audit.GetEntries(wssQuery);
                // enumerate through audit log and read entries
                foreach (SPAuditEntry entry in auditCol)
                {
                    
                    if (Array.IndexOf(eventTypesToSave, entry.Event.ToString().ToLower()) >= 0)
                    {
                        EventLogItem eLI;
                        try
                        {
                            eLI.Server = Truncate(siteurl, 49).TrimEnd() + "/";
                            eLI.DocLocation = Truncate(entry.DocLocation, 2000).TrimEnd();
                            eLI.Event = Truncate(entry.Event.ToString(), 20).TrimEnd();
                            eLI.Occurred = entry.Occurred;
                            eLI.LoginName = Truncate(web.SiteUsers.GetByID(entry.UserId).LoginName, 30).TrimEnd();
                            eLI.Name = Truncate(web.SiteUsers.GetByID(entry.UserId).Name, 200).TrimEnd();
                            eLI.Source = Truncate(entry.EventSource.ToString(), 50).TrimEnd();
                            eLI.ItemId = Truncate(entry.ItemId.ToString(), 40).TrimEnd();
                            eLI.LocationType = Truncate(entry.LocationType.ToString(), 20).TrimEnd();

                            using (SqlCommand com = new SqlCommand())
                            {
                                com.Connection = conn;
                                com.CommandType = CommandType.StoredProcedure;
                                com.CommandText = "sp_InsertEventLogItem";
                                com.Parameters.AddWithValue("@Server", eLI.Server);
                                com.Parameters.AddWithValue("@DocLocation", eLI.DocLocation);
                                com.Parameters.AddWithValue("@Event", eLI.Event);
                                com.Parameters.AddWithValue("@Occurred", eLI.Occurred);
                                com.Parameters.AddWithValue("@LoginName", eLI.LoginName);
                                com.Parameters.AddWithValue("@Name", eLI.Name);
                                com.Parameters.AddWithValue("@Source", eLI.Source);
                                com.Parameters.AddWithValue("@ItemID", eLI.ItemId);
                                com.Parameters.AddWithValue("@LocationType", eLI.LocationType);
                                com.ExecuteNonQuery();
                            }
                        }
                        catch (Exception ex) { 

                            using (SqlCommand com = new SqlCommand())
                            {
                                com.Connection = conn;
                                com.CommandType = CommandType.StoredProcedure;
                                com.CommandText = "sp_InsertError";
                                com.Parameters.AddWithValue("@Server", Truncate(siteurl, 50));
                                com.Parameters.AddWithValue("@SitePath", Truncate(site.Url,200));
                                com.Parameters.AddWithValue("@Description", Truncate(ex.Message, 100).TrimEnd());
                                com.Parameters.AddWithValue("@Date", DateTime.Now);
                                com.ExecuteNonQuery();
                            }   
                        }
                    }
                }
                if (clearAuditHistory)
                {
                    site.Audit.DeleteEntries(DateTime.Now);
                }
            }
        }
        private static String Truncate(String input, int maxLength)
        {
            if (input.Length > maxLength)
                return input.Substring(0, maxLength);
            return input;
        }
        #endregion
    }
}
